﻿using MyModels;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace MyRepository.BASE
{
    public class BaseRepository<TEntity> : IBaseRepository<TEntity> where TEntity : class, new()
    {
        private readonly SqlSugarScope _client;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="sqlSugar"></param>
        public BaseRepository(ISqlSugarClient sqlSugar)
        {
            _client = sqlSugar as SqlSugarScope;
        }
         public ISqlSugarClient Db => _client;

        public async Task<long> Add(TEntity entity)
        {
            ////var i = await Task.Run(() => _db.Insertable(entity).ExecuteReturnBigIdentity());
            //////返回的i是long类型,这里你可以根据你的业务需要进行处理
            ////return (int)i;

            //var insert = _db.Insertable(entity);

            ////这里你可以返回TEntity，这样的话就可以获取id值，无论主键是什么类型
            ////var return3 = await insert.ExecuteReturnEntityAsync();

            //return await insert.ExecuteReturnSnowflakeIdAsync();
            var insert = _client.Insertable(entity);
            return await insert.ExecuteReturnSnowflakeIdAsync();
        }

        /// <summary>
        /// 写入实体数据
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="insertColumns"></param>
        /// <returns></returns>
        public async Task<long> Add(TEntity entity, Expression<Func<TEntity, object>> insertColumns = null)
        {
            var insert = _client.Insertable(entity);
            if (insertColumns != null)
            {
                return await insert.InsertColumns(insertColumns).ExecuteReturnSnowflakeIdAsync();
            }
            else
            {
                return await insert.ExecuteReturnSnowflakeIdAsync();
            }
        }

        public async Task<List<long>> Add(List<TEntity> entities)
        {
            return await _client.Insertable(entities.ToArray()).ExecuteReturnSnowflakeIdListAsync();
        }

        public async Task<bool> Update(TEntity entity)
        {
            return await _client.Updateable(entity).ExecuteCommandHasChangeAsync();
        }

        public async Task<bool> Update(TEntity entity, string where)
        {
            return await _client.Updateable(entity).Where(where).ExecuteCommandHasChangeAsync();
        }

        public async Task<bool> Update(List<TEntity> entities)
        {
            return await _client.Updateable(entities).ExecuteCommandHasChangeAsync();
        }
        public async Task<bool> Update(object operateAnonymousObjects)
        {
            return await _client.Updateable<TEntity>(operateAnonymousObjects).ExecuteCommandAsync() > 0;
        }

        public async Task<bool> Update(string sql, SugarParameter[] parameters = null)
        {
            return await _client.Ado.ExecuteCommandAsync(sql, parameters) > 0;
        }

        public async Task<bool> Update(TEntity entity, List<string> listColumns = null, List<string> listIgnoreColumns = null, string where = "")
        {
            var up = _client.Updateable(entity);
            if (listIgnoreColumns != null && listIgnoreColumns.Count > 0)
            {
                up = up.IgnoreColumns(listIgnoreColumns.ToArray());
            }

            if (listColumns != null && listColumns.Count > 0)
            {
                up = up.UpdateColumns(listColumns.ToArray());
            }

            if (!string.IsNullOrEmpty(where))
            {
                up = up.Where(where);
            }

            return await up.ExecuteCommandHasChangeAsync();
        }

        public async Task<bool> Delete(TEntity entity)
        {
            return await _client.Deleteable(entity).ExecuteCommandHasChangeAsync();
        }

        public async Task<bool> DeleteById(object id)
        {
            return await _client.Deleteable<TEntity>().In(id).ExecuteCommandHasChangeAsync();
        }

        public async Task<bool> DeleteByIds(object[] ids)
        {
            return await _client.Deleteable<TEntity>().In(ids).ExecuteCommandHasChangeAsync();
        }

        public async Task<List<TEntity>> Query()
        {
            return await _client.Queryable<TEntity>().ToListAsync();
        }
        public async Task<List<TEntity>> Query(string where)
        {
            return await _client.Queryable<TEntity>().WhereIF(!string.IsNullOrEmpty(where), where).ToListAsync();
        }
        public async Task<List<TEntity>> Query(Expression<Func<TEntity, bool>> expression)
        {
            return await _client.Queryable<TEntity>().WhereIF(expression != null, expression).ToListAsync();
        }

        public async Task<List<TResult>> Query<TResult>(Expression<Func<TEntity, TResult>> expression)
        {
            return await _client.Queryable<TEntity>().Select(expression).ToListAsync();
        }

        public async Task<List<TResult>> Query<TResult>(Expression<Func<TEntity, TResult>> expression, Expression<Func<TEntity, bool>> whereExpression, string orderByField)
        {
            return await _client.Queryable<TEntity>()
                .OrderByIF(!string.IsNullOrEmpty(orderByField), orderByField)
                .WhereIF(whereExpression != null, whereExpression)
                .Select(expression).ToListAsync();
        }

        public async Task<List<TEntity>> Query(Expression<Func<TEntity, bool>> whereExpression, string orderByField)
        {
            return await _client.Queryable<TEntity>().WhereIF(whereExpression != null, whereExpression)
                .OrderByIF(!string.IsNullOrEmpty(orderByField), orderByField).ToListAsync();
        }

        public async Task<List<TEntity>> Query(Expression<Func<TEntity, bool>> whereExpression, Expression<Func<TEntity, object>> orderByExpression, bool isAsc)
        {
            return await _client.Queryable<TEntity>().WhereIF(whereExpression != null, whereExpression)
                .OrderByIF(orderByExpression != null, orderByExpression, isAsc ? OrderByType.Asc : OrderByType.Desc).ToListAsync();
        }

        public async Task<List<TEntity>> Query(string where, string orderByField)
        {
            return await _client.Queryable<TEntity>().WhereIF(!string.IsNullOrEmpty(where), where)
                .OrderByIF(!string.IsNullOrEmpty(orderByField), orderByField).ToListAsync();
        }

        public async Task<List<TEntity>> Query(Expression<Func<TEntity, bool>> whereExpression, int intTop, string orderByField)
        {
            return await _client.Queryable<TEntity>().WhereIF(whereExpression != null, whereExpression)
                .OrderByIF(!string.IsNullOrEmpty(orderByField), orderByField).Take(intTop).ToListAsync();
        }

        public async Task<List<TEntity>> Query(string where, int intTop, string orderByField)
        {
            return await _client.Queryable<TEntity>()
                .WhereIF(!string.IsNullOrEmpty(where), where)
                .OrderByIF(!string.IsNullOrEmpty(orderByField), orderByField)
                .Take(intTop).ToListAsync();
        }

        public async Task<List<TEntity>> Query(Expression<Func<TEntity, bool>> whereExpression, int pageIndex, int pageSize, string orderByField)
        {
            return await _client.Queryable<TEntity>()
                .WhereIF(whereExpression != null, whereExpression)
                .OrderByIF(!string.IsNullOrEmpty(orderByField), orderByField)
                .ToPageListAsync(pageSize, pageIndex);
        }

        public async Task<List<TEntity>> Query(string where, int pageIndex, int pageSize, string orderByField)
        {
            return await _client.Queryable<TEntity>()
                .WhereIF(!string.IsNullOrEmpty(where), where)
                .OrderByIF(!string.IsNullOrEmpty(orderByField), orderByField)
                .ToPageListAsync(pageIndex, pageSize);
        }

        public async Task<TEntity> QueryById(object id)
        {
            return await _client.Queryable<TEntity>().In(id).SingleAsync();
        }

        public async Task<TEntity> QueryById(object id, bool blnUseCache = false)
        {
            return await _client.Queryable<TEntity>().WithCacheIF(blnUseCache, 10).In(id).SingleAsync();
        }

        public async Task<List<TEntity>> QueryByIds(object[] listIds)
        {
            return await _client.Queryable<TEntity>().In(listIds).ToListAsync();
        }

        public async Task<List<TEntity>> QuerySQL(string sql, SugarParameter[] parameters = null)
        {
            return await _client.Ado.SqlQueryAsync<TEntity>(sql, parameters);
        }

        public async Task<DataTable> QueryTable(string sql, SugarParameter[] parameters = null)
        {
            return await _client.Ado.GetDataTableAsync(sql, parameters);
        }

        public async Task<List<TResult>> QueryMuch<T, T2, T3, TResult>(
            Expression<Func<T, T2, T3, object[]>> joinExpression,
            Expression<Func<T, T2, T3, TResult>> selectExpression,
            Expression<Func<T, T2, T3, bool>> whereLambda = null) where T : class, new()
        {
            if (whereLambda == null)
            {
                return await _client.Queryable(joinExpression).Select(selectExpression).ToListAsync();
            }
            return await _client.Queryable(joinExpression).Where(whereLambda).Select(selectExpression).ToListAsync();
        }

        public async Task<PageModel<TEntity>> QueryPage(
            Expression<Func<TEntity, bool>> whereExpression, 
            int pageIndex = 1, int pageSize = 20, string orderByFidels = null)
        {
            RefAsync<int> total = 0;
            var list = await _client.Queryable<TEntity>().WhereIF(whereExpression != null, whereExpression)
               .OrderByIF(!string.IsNullOrEmpty(orderByFidels), orderByFidels)
               .ToPageListAsync(pageIndex, pageSize, total);

            return new PageModel<TEntity>(pageIndex, total, pageSize, list);
        }


        public async Task<PageModel<TResult>> QueryTabsPage<T, T2, TResult>(
            Expression<Func<T, T2, object[]>> joinExpression, 
            Expression<Func<T, T2, TResult>> selectExpression, 
            Expression<Func<TResult, bool>> whereExpression, 
            int pageIndex, int pageSize, string orderByFields = null)
        {
            RefAsync<int> total = 0;
            var list = await _client.Queryable<T,T2>(joinExpression)
                .Select(selectExpression)
                .WhereIF(whereExpression!=null,whereExpression)
                .OrderByIF(!string.IsNullOrEmpty(orderByFields), orderByFields)
                .ToPageListAsync(pageIndex,pageSize, total);

            return new PageModel<TResult>(pageIndex, total, pageSize, list);
        }

        public async Task<PageModel<TResult>> QueryTabsPage<T, T2, TResult>(
            Expression<Func<T, T2, object[]>> joinExpression, 
            Expression<Func<T, T2, TResult>> selectExpression, 
            Expression<Func<TResult, bool>> whereExpression, 
            Expression<Func<T, object>> groupExpression, 
            int pageIndex, int pageSize, string orderByFields = null)
        {
            RefAsync<int> total = 0;
            var list = await _client.Queryable<T,T2>(joinExpression).GroupBy(groupExpression)
                .Select(selectExpression)
                .WhereIF(whereExpression!= null,whereExpression)
                .OrderByIF(!string.IsNullOrEmpty(orderByFields),orderByFields)
                .ToPageListAsync(pageIndex,pageSize, total);

            return new PageModel<TResult> (pageIndex, total, pageSize, list);
        }


    }
}
